package InnerGameParts;

//import java.awt.Color;
//import java.awt.Graphics;
import java.awt.Graphics2D;
//import java.awt.Shape;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
//import java.util.Stack;

import javax.imageio.ImageIO;


import OuterGameParts.Requests;


public class PirateShip implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -7928827157754672864L;
	private static int GRAPHICS_WIDTH ; 
	private static int GRAPHICS_HEIGHT ;
	private final static int BOAT_LENGHT = 305;
	private final static int BOAT_WIDTH = 100;
	private final static int MOVE_CONSTANT = 5;
	private final static int MAX_AMMO = 24;
	private static final int CREATE_DIST = 5;
	private static int RAN_CHANCE_RELOAD = 50;
	
	
	/*
	 * Boat Measurements
	 */
	private final static int Y_DIST_FROM_CENTER_TO_TOP = 140;
	
	private final static int X_DIST_FROM_CENTER_TO_BASECURVE = 30;
	private final static int Y_DIST_FROM_CENTER_TO_BASECURVE = 90;
	
	private final static int X_DIST_FROM_CENTER_TO_JUT_OUT_BIT = 40;
	private final static int Y_DIST_FROM_CENTER_TO_JUT_OUT_BIT= 10;
	
	private final static int X_DIST_FROM_CENTER_TO_BOTTOM = 20;
	private final static int Y_DIST_FROM_CENTER_TO_BOTTOM= 135;
	
	private final static int Y_DIST_FROM_CENTER_TO_VERY_BOTTOM= 140;
	
	private final static int SHOOTABLE_AREA = 100;
	
	
	

	//private final String mImagePath = "pirate_ship_wshadow_SV.png";
	//private BufferedImage mImage;
	private int mDirection;
	private int mXposition;
	private int mYposition;

	private int mHealth;
	private int mLeftAmmo;
	private int mRightAmmo;
	private String playerName;
	private int playerScore;


	//private final static Shape SHIP_SHAPE = new Shape();

	private int shipHeight = 100;
	private int shipWidth =  50;
	private int shipBowHieght = 50;
	private Random myRan;

	private int mScore;
	private int mMultiplier;

	/**
	 * 
	 * Player requests
	 * 
	 */
	private Requests[] requests = new Requests[5];


	/*private int randomAmount(final boolean isX){


		if(isX){

			System.out.println((int)(myRan.nextInt() * Math.sin(Math.toRadians(mDirection))));

			return  (int)((myRan.nextInt(BOAT_LENGHT/2) - BOAT_LENGHT) * Math.sin(Math.toRadians(mDirection)));

		}else{

			return  (int)((myRan.nextInt(BOAT_LENGHT/2) - BOAT_LENGHT) * Math.cos(Math.toRadians(mDirection)));

		}




	}*/

	public PirateShip(){

		mDirection = 0;
		mXposition = 50;
		mYposition = 50;

		mHealth = 50;
		mLeftAmmo = MAX_AMMO;
		mRightAmmo = MAX_AMMO;

		myRan = new Random();
		//mImage = null;

		mScore = 0;
		mMultiplier = 0;

		try {

			//	mImage = ImageIO.read( new File(mImagePath));

		}catch(final Exception ex){

			ex.printStackTrace();

		}
		//GRAPHICS_WIDTH = mImage.getWidth();
		//GRAPHICS_HEIGHT = mImage.getHeight();
	}


	public int getHealth(){

		return mHealth;

	}

	public synchronized void updateAmmo(){



		if(mRightAmmo < MAX_AMMO && myRan.nextInt(RAN_CHANCE_RELOAD) == 0){
			mRightAmmo++;
		}

		if(mLeftAmmo < MAX_AMMO && myRan.nextInt(RAN_CHANCE_RELOAD) == 0 ){
			mLeftAmmo++;
		}


	}

	public int getRightAmoo(){

		return mRightAmmo;

	}


	public  int getLeftAmoo(){

		return mLeftAmmo;

	}

	public int getDirection(){

		return mDirection;

	}

	public int getY(){

		return mYposition;

	}

	public int getX(){

		return mXposition;

	}

	public Requests[] getRequests(){

		return requests;
	}

	public void requestLeft(){


		requests[1] = Requests.TURN_LEFT;

	}

	public void requestRight(){

		requests[1] = Requests.TURN_RIGHT;
	}

	public void requestForward(){

		requests[0] = Requests.MOVE_FORWARD;

	}

	public void requestShootLeft(){

		requests[3] = Requests.SHOOT_LEFT;

	}

	public void requestShootRight(){

		requests[4] = Requests.SHOOT_RIGHT;

	}


	public void derequestLeft(){


		requests[1] = null;

	}

	public void derequestRight(){

		requests[1] = null;
	}

	public void derequestForward(){

		requests[0] = null;

	}

	public void derequestShootLeft(){

		requests[3] = null;

	}

	public void derequestShootRight(){

		requests[4] = null;

	}


	public void turnLeft(){

		mDirection -= MOVE_CONSTANT;

		if(mDirection < 0){

			mDirection += 360; 

		}
	}	

	/*
	 * 
	 * inomine1
	 * 
	 */

	public void turnRight(){


		mDirection += MOVE_CONSTANT;

		if(mDirection >= 360){

			mDirection -= 360; 

		}



	}

	public synchronized void moveForward(Wind theWind){


		int shipMovementX = shipMoveX(theWind);
		int shipMovementY = shipMoveY(theWind);

		mXposition +=  shipMovementX; //+ theWind.getWindMoveX();
		mYposition -= shipMovementY ;//+ theWind.getWindMoveY();	

		System.out.println(mXposition +"," + mYposition);

		/* int Xs [] = createTheXArray();
		StringBuilder myBuilder = new StringBuilder();
		for(int count  = 0 ; count <  Xs.length; count++){


			myBuilder.append(count + ":" + Xs[count] + ",");


		}
		System.out.println(myBuilder.toString());
		//*/


	}

	private synchronized int shipMoveX(Wind theWind){

		return (int) (10 *

				theWind.windPower(mDirection)*
				Math.sin(Math.toRadians(mDirection)));

	}

	private synchronized int shipMoveY(Wind theWind){

		return (int) (10 * 
				theWind.windPower(mDirection) *
				Math.cos(Math.toRadians(mDirection)));

	}

	public synchronized void hit(final int damageTaken){

		mHealth -= damageTaken;


		if(mHealth <= 0){


			//causes the ships to be destroyed
			// and spawns it some where else.
			destroy();

		}

	}


	private void destroy(){


	}

	public synchronized List<CannonBall> shootLeft(){

		List<CannonBall> cannonShots  = new LinkedList<CannonBall>();

		int [] XY = rotate(-BOAT_WIDTH/2 - CREATE_DIST, myRan.nextInt(SHOOTABLE_AREA) - SHOOTABLE_AREA/2); 		
		
		if( mLeftAmmo  > 0){

			mLeftAmmo--;

			cannonShots.add( new CannonBall(mDirection - 90,
					mXposition + XY[0], mYposition + XY[1] ));


		}


		return cannonShots;

	}

	public synchronized List<CannonBall> shootRight(){

		List<CannonBall> cannonShots  = new LinkedList<CannonBall>();

		int [] XY = rotate(BOAT_WIDTH/2 + CREATE_DIST, myRan.nextInt(SHOOTABLE_AREA) - SHOOTABLE_AREA/2); 
		
		if( mRightAmmo  > 0){

			mRightAmmo--;

			cannonShots.add( new CannonBall(mDirection + 90,
					mXposition + XY[0], mYposition + XY[1]));
		}

		return cannonShots;
	}


	public boolean collide(PirateShip s){

		//TODO put in point working algoruim


		return false;
	}


	private boolean pointOnCorrectSideOfLine(int x,  int y,  int x0, int  y0, int  x1, int  y1 ){


		if( (y - y0) * (x1 - x0) - (x - x0)*(y1 - y0) > 0){

			return true;

		}

		return false;

	}

	public int [][] createTheXYArray(){

		int [][] XY =  new int [8][2];

		/*XY[0][0] = -BOAT_WIDTH/2 + 20;
		XY[0][1] = -BOAT_LENGHT/2 + 50;
		
		XY[1][0] = 0;
		XY[1][1] = -BOAT_LENGHT/2 - 5;
		
		XY[2][0] = BOAT_WIDTH/2 - 20;
		XY[2][1] = -BOAT_LENGHT/2  + 50;
		
		XY[3][0] = BOAT_WIDTH/2 - 25;
		XY[3][1] = BOAT_LENGHT/2 - 10;
		
		XY[4][0] = - BOAT_WIDTH/2 + 25;
		XY[4][1] = BOAT_LENGHT/2 - 10 ;
		*
		*
		* Point which make up th hit box:S
		
		        0
		       /\
		      /  \ 
		 *   /    \
		 * 7/      \ 1
		 *  |      |
		 *  |      |
		 *  |      |
		 * 6|      |2
		 *   |    |
		 *   |    |
		 *   |    |
		 *  5|_  _|3
		 *     ..
		 *      4
		 * 
		 */
		
		
		
		
		
		XY[0][0] = 0;
		XY[0][1] = -Y_DIST_FROM_CENTER_TO_TOP;
		
		XY[1][0] = X_DIST_FROM_CENTER_TO_BASECURVE;
		XY[1][1] = -Y_DIST_FROM_CENTER_TO_BASECURVE;
		
		XY[2][0] = X_DIST_FROM_CENTER_TO_JUT_OUT_BIT;
		XY[2][1] = Y_DIST_FROM_CENTER_TO_JUT_OUT_BIT;
		
		XY[3][0] = X_DIST_FROM_CENTER_TO_BOTTOM;
		XY[3][1] = Y_DIST_FROM_CENTER_TO_BOTTOM;
		
		XY[4][0] = 0;
		XY[4][1] = Y_DIST_FROM_CENTER_TO_VERY_BOTTOM;
		
		XY[5][0] = -X_DIST_FROM_CENTER_TO_BOTTOM;
		XY[5][1] = Y_DIST_FROM_CENTER_TO_BOTTOM;
				
		XY[6][0] = -X_DIST_FROM_CENTER_TO_JUT_OUT_BIT;
		XY[6][1] = Y_DIST_FROM_CENTER_TO_JUT_OUT_BIT;
		
		XY[7][0] = -X_DIST_FROM_CENTER_TO_BASECURVE;
		XY[7][1] = -Y_DIST_FROM_CENTER_TO_BASECURVE;
		
		
		
		
		
		
		
		
		
		

		//does the rotating
		for(int count = 0 ; count < XY.length; count++){


			XY[count] = rotate(XY[count][0], XY[count][1] );
			XY[count][0] += mXposition; 
			XY[count][1] +=  mYposition;


		}


		return XY;
	}

	/**
	 * 
	 * Uses rotation formula :
	 *  
	 *  
	 *  X = x cos E - y sin E
	 *
	 *Y =  x sin E + y cos E
	 * 
	 * 
	 */
	private int [] rotate(int x, int y ){


		int [] XY = new int [2];
		XY[0] = (int) ( x * Math.cos(Math.toRadians(mDirection)) - y * Math.sin(Math.toRadians(mDirection)));
		XY[1] = (int)( x * Math.sin(Math.toRadians(mDirection)) + y * Math.cos(Math.toRadians(mDirection)));


		return XY;
	}

	public boolean collide(CannonBall ball){



		//gets all the points need to preform the calculation
		int x = ball.getX();
		int y = ball.getY();
		int [][] XY = createTheXYArray();



		for ( int count = 0 ; count < XY.length -1; count++)
		{
			if(!pointOnCorrectSideOfLine(x, y, XY[count][0], XY[count][1], XY[count+ 1][0], XY[count + 1][1])){

				return false;

			}
		}

		//do the last check by hand
		if(!pointOnCorrectSideOfLine(x, y, XY[XY.length -1 ][0], XY[XY.length - 1][1], XY[0][0], XY[0][1])){

			return false;

		}

		
		System.out.println("collide");
		return true;


	}


}
